package cn.edu.dlut.port.isp.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.springframework.stereotype.Service;

import arjuna.javasims.dist.UniformStream;
import cn.edu.dlut.port.isp.bean.teach.simulation.Constants;
import cn.edu.dlut.port.isp.bean.teach.simulation.PortBean;
import cn.edu.dlut.port.isp.bean.teach.simulation.SchemeForm;
import cn.edu.dlut.port.isp.bean.teach.simulation.Sdata;
import cn.edu.dlut.port.optiplan.elem.Anchorage;
import cn.edu.dlut.port.optiplan.elem.Current;
import cn.edu.dlut.port.optiplan.elem.DesignedECDimension;
import cn.edu.dlut.port.optiplan.elem.DoubleEC;
import cn.edu.dlut.port.optiplan.elem.EntranceChannel;
import cn.edu.dlut.port.optiplan.elem.SingleEC;
import cn.edu.dlut.port.optiplan.elem.Soil;
import cn.edu.dlut.port.optiplan.elem.Terminal;
import cn.edu.dlut.port.optiplan.elem.Tide;
import cn.edu.dlut.port.optiplan.elem.Wave;
import cn.edu.dlut.port.optiplan.elem.Weather;
import cn.edu.dlut.port.optiplan.sim.nav.v2.OneECService;
import cn.edu.dlut.port.optiplan.sim.nav.v2.OneNavSimSys;


@Service
public class TeachServiceImp implements TeachService{
	private PortBean port;
	@Override
	public void initPort(PortBean pb) {
		this.port=pb;	
	}
    public Object checkAndRunModelParams(SchemeForm schemeForm) {
	    
        int schemsIdx = 0;
        try {
            double width = 0, depth0, depth;
            List<double[]> schems = new ArrayList<double[]>();
            String isSDEC = schemeForm.getIssdec();
            String soilStr = schemeForm.getSoil();
            String widthStr = schemeForm.getWidw();
            final String depth0Str =schemeForm.getDep0();
            final String depthStr =schemeForm.getDep();
            width = Double.parseDouble(widthStr);
            depth0 = Double.parseDouble(depth0Str);
            depth = Double.parseDouble(depthStr);
            double v = schemeForm.getV();
            double ts = schemeForm.getTs();
            port.setV(v);
            final List<Sdata> list= schemeForm.getList();
            for (int i = 0; i < list.size(); i++) {
                double[] zAndL = new double[2];
                String obj01 = list.get(i).getWaterlevel().toString();
                String obj02 = list.get(i).getLength().toString();
                if (obj01 != null && obj02 != null && obj01.length() > 0 && obj02.length() > 0 && !obj01.equals("0.0") &&  !obj02.equals("0.0") ) {
                    zAndL[0] = Double.parseDouble(obj01);
                    zAndL[1] = Double.parseDouble(obj02);
                    schems.add(zAndL);
                }            
            }
            int calNum = schems.size();
            if(calNum==0)
            	return "e1";
  
            Terminal terminal = port.toTerminal();
            Tide tide = port.getTide();
            Wave wave = port.getWave();
            double safeDuration = 1.0 / 6.0;
            Soil soil = port.getSoil();
           // final int soilType = Soil.getType(soilStr);
           // soil.setType(soilType);
            soil.setType(Integer.parseInt(soilStr));
            System.out.println("soilTYpe\t" + soilStr);
            Current current = port.getCurrent();
            cn.edu.dlut.port.optiplan.sim.nav.ShipBean[] arrivedships = terminal.shipArrivalsByEachBerth(Constants.SIMULATIONHOURS);
            
            Anchorage anchor = new Anchorage(tide);
            Weather weather = new Weather(port.getOperationalDay(), new UniformStream(0, 365));

            for (double[] zll : schems) {
                double rwl = zll[0];
                double belv = rwl - depth;
                DesignedECDimension d = new DesignedECDimension(zll[1], width, depth, rwl, belv);
                System.out.append("CHannel demension:\t" + d.getBottomElevation() + "\t" + d.getNavigationDepth() + "\t" + d.getNavigationWaterLevel());
                EntranceChannel channel;
                if (isSDEC.equals("1")) {//单线
                    channel = new SingleEC(terminal, tide, wave, current, soil, d, safeDuration);
                } else {
                    channel = new DoubleEC(terminal, tide, wave, current, soil, d, safeDuration);
                }

                System.out.println("Navigable water level:\t" + channel.getDefaultNavigableDepth());
                System.out.println("Is Navigable? \t" + channel.isNavigableWaterLevelReasonable());
                if (channel.isNavigableWaterLevelReasonable()) {
                    schemsIdx++;
                } else {
                    throw new NoSuchElementException();
                }
            }
            List<String> results=new ArrayList<String>();
            for (double[] zll : schems) {
                double rwl = zll[0];
                double belv = rwl - depth;
                DesignedECDimension d = new DesignedECDimension(zll[1], width, depth, rwl, belv);
                EntranceChannel channel;
                if (isSDEC.equals("1")) {//单线
                    channel = new SingleEC(terminal, tide, wave, current, soil, d, safeDuration);
                } else {
                    channel = new DoubleEC(terminal, tide, wave, current, soil, d, safeDuration);
                }
                OneECService service = new OneECService(terminal, channel, anchor, weather, arrivedships);
                OneNavSimSys sys = new OneNavSimSys(service);
                sys.await();
                TreeMap<String, Double[]> waitAndTonMap = new TreeMap<>();
                int numServiced = service.numServiced;
                int numArrived = service.numArrived;
                int numRejected = service.numRejected;
                int numEntered = service.numEntered;
                int numLeaved = service.numLeaved;
                double portServiceLevel = service.portServiceLevel;
                double channelUtilizationRate = service.channelUtilizationRate;
                double maxTimeWaiting = service.maxDurationWait;
                double annualTimeWaiting = service.annualDurationWait;
                double aveTimeWaiting = service.aveDurationWait;
                double maxTimeWait4Berth = service.maxDurationWait4Berth;
                double annualTimeWait4Berth = service.annualDurationWait4Berth;
                double aveTimeWait4Berth = service.aveDurationWait4Berth;
                double maxTimeWait4Channel = service.maxDurationWait4Channel;
                double annualTimeWait4Channel = service.annualDurationWait4Channel;
                double aveTimeWait4Channel = service.aveDurationWait4Channel;
                double maxTimeAtBerth = service.maxDurationAtBerth;
                double aveTimeAtBerth = service.aveDurationAtBerth;
                double annualTimeAtBerth = service.annualDurationAtBerth;
                double aveWaitingShip = service.aveNumWaitingShip;
                double annualTons = service.annualTons;
                double vesselTime = service.vesselTime;
                int maxWaitingShip = Integer.MIN_VALUE;
                ConcurrentHashMap<String, CopyOnWriteArraySet> shipsInACMaxMap;
                int maxWS = service.maxNumWaitingShip;
                if (maxWaitingShip < maxWS) {
                    maxWaitingShip = maxWS;
                    shipsInACMaxMap = service.shipsMaxMap;
                }
               // Map<Integer, Double[]> waitAndTonMapt=service.waitAndTonMap;
                HashMap<String, Double[]> waitAndTonMap01=service.waitAndTonMap;
                System.out.println("----------------waitAndTonMap01---------------------"+waitAndTonMap01);
                Iterator titer = waitAndTonMap01.entrySet().iterator();
                StringBuilder sb = new StringBuilder();
              
                while (titer.hasNext()) {
                    Map.Entry ent = (Map.Entry) titer.next();
                    System.out.println("----------------进入循环ent---------------------"+ent.getKey()+"-------length-----"+((Double[])ent.getValue()).length);
                    // int keyt = Integer.parseInt(ent.getKey().toString());
                      String keyt= ent.getKey().toString();
                      //  Double[] valuet01 = waitAndTonMap01.get(keyt);
                   Double[] valuet01 =(Double[])ent.getValue();
                    System.out.println("----------------进入循环valuet01---------------------"+valuet01);
                    if (waitAndTonMap.containsKey(keyt)) {
                        Double[] valuets02 = waitAndTonMap.get(keyt);
                        valuets02[0] = valuets02[0] + valuet01[0];
                        valuets02[1] = valuets02[1] + valuet01[1];
                        waitAndTonMap.put(keyt, valuets02);
                    } else {
                        waitAndTonMap.put(keyt, valuet01);
                    }
                    sb.append(keyt).append(":").append(valuet01[0].intValue()).append(";");
                    System.out.println("what happened? " + keyt + ":" + valuet01[0] + "*" + valuet01[1] + ";");
                }
                System.out.println("------------------result-----------------------");
                System.out.println(sb);
                results.add(sb.toString());
                sys.reset();
            }
            return results;
        }catch (NullPointerException ex) {
        	return "e1";
        } catch (NumberFormatException nfe) {
        	return "e2";
        } catch (NoSuchElementException nse) {
        	String pos=(schemsIdx + 1)+"";
        	System.out.println("方案" + pos + "航道通航水位不能满足船舶通航要求！");
        	return pos;
        }catch(Exception e)
        {
        	System.out.println("出现异常：");
        	e.printStackTrace();
        	return null;
        }
    }

}
